package com.canic.dkd.authorization.security;


import com.canic.dkd.authorization.staff.entity.SysRole;
import com.canic.dkd.authorization.staff.entity.SysUser;
import com.canic.dkd.authorization.staff.service.SysPermissionService;
import com.canic.dkd.authorization.staff.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * RBAC 所有的请求都会到这里做权限校验
 * @author YUY
 */
@Slf4j
@Component("rbacService")
public class RbacAuthorityService {

    @Bean
    private AntPathMatcher antPathMatcher() {
        return new AntPathMatcher();
    }

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysUserDetailsService sysUserDetailsService;

    @Autowired
    private SysPermissionService sysPermissionService;

    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        log.info("current request is:" + request.getRequestURI());
        List<SimpleGrantedAuthority> grantedAuthorities = (List<SimpleGrantedAuthority>)authentication.getAuthorities();
        String token = request.getHeader("token");

        /**
         * 未登录 --> token验证通过:重构系统用户authentication,继续验权限  --> token验证不通过：拦截
          */
        if (grantedAuthorities != null) {
            SimpleGrantedAuthority roleName = grantedAuthorities.get(0);
            if(roleName.getAuthority().equals("ROLE_ANONYMOUS")){
                // 未登录&未提供token,直接拦截
                if(token == null){
                    return false;
                }
                // 未登录&提供token但token未通过验证
                String userName = JwtTokenUtil.getUsernameFromToken(token);
                SysUser user = sysUserService.getUserByName(userName);
                if (user == null){
                    return false;
                }else{
                    Authentication refreshAuthentication = refreshAuthentication(user, request);
                    // 更新 authentication
                    grantedAuthorities = (List<SimpleGrantedAuthority>)refreshAuthentication.getAuthorities();
                }
            }
        }

        // 该URL所需要的角色
        List<SysRole> urlRoleList = sysPermissionService.getRoleListByPermissionUrl(request.getRequestURI());
        // 登录人拥有的角色
        List<String> userRoleList = grantedAuthorities.stream().map(authory -> authory.getAuthority()).collect(Collectors.toList());
        String userRoleStr= String.join(",", (String[])userRoleList.toArray(new String[userRoleList.size()]));
        // 该用户的角色与该URL所需要的角色有重合
        for(SysRole role : urlRoleList) {
              if(userRoleStr.contains(role.getName())){
                  return true;
              }
        }

        return false;
    }

    /**
     * 重建该用户当前的权限
     * @param user
     */
    private Authentication  refreshAuthentication(SysUser user, HttpServletRequest request){
        UserDetails userDetails = sysUserDetailsService.loadUserByUsername(user.getName());
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return authentication;
    }

}
